package com.ruoyi.web.service;


import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.IsoFields;
import java.util.*;


@Service
public class C2PipeSucRateService {
    @Autowired
    private DruidDataSource druidDataSource;

    public Map<String, Object> getNodeSuccessRateByWeeks() {
        // 返回数据结构
        Map<String, List<String>> timePeriods = new HashMap<>();
        List<String> weeks = new ArrayList<>();
        Map<String, List<Double>> nodeSuccessRates = new HashMap<>();

        // SQL 查询所有记录
        String sql = "SELECT `buildTime`, `nodeName`, COALESCE(`integratedStatus`, 0) AS `integratedStatus` FROM `cicd_integrated_info`;";

        // 使用 TreeMap 按时间和 nodeName 存储数据
        Map<String, Map<String, int[]>> weeklyNodeStats = new TreeMap<>();

        try (Connection conn = druidDataSource.getConnection();
             PreparedStatement stmt = conn.prepareStatement(sql);
             ResultSet rs = stmt.executeQuery()) {

            while (rs.next()) {
                LocalDateTime buildTime = rs.getObject("buildTime", LocalDateTime.class);
                String nodeName = rs.getString("nodeName");
                int integratedStatus = rs.getInt("integratedStatus");

                if(!nodeName.equals("CICD_C2_SOC")) // demo2024 暂时值返回C2_SOC
                    continue;

                // 获取自然周周期，例如 "2024-W01"
                String week = getWeekPeriod(buildTime);

                // 初始化每周每个 nodeName 的统计数据
                weeklyNodeStats.putIfAbsent(week, new HashMap<>());
                weeklyNodeStats.get(week).putIfAbsent(nodeName, new int[]{0, 0}); // totalCount, zeroStatusCount

                // 更新统计
                int[] stats = weeklyNodeStats.get(week).get(nodeName);
                stats[0]++; // 总记录数加1
                if (integratedStatus == 0) {
                    stats[1]++; // integratedStatus == 0 的次数加1
                }
            }

            // 获取所有周的顺序（已按升序排列）
            for (Map.Entry<String, Map<String, int[]>> weekEntry : weeklyNodeStats.entrySet()) {
                String week = weekEntry.getKey();
                weeks.add(week);  // 添加周
            }

            // 遍历每个 nodeName，初始化其在每周的成功率列表
            Set<String> allNodeNames = new HashSet<>();
            for (Map.Entry<String, Map<String, int[]>> weekEntry : weeklyNodeStats.entrySet()) {
                Map<String, int[]> nodeData = weekEntry.getValue();
                for (String nodeName : nodeData.keySet()) {
                    allNodeNames.add(nodeName);
                }
            }

            // 对每个 nodeName 遍历周，计算每周的成功率
            for (String nodeName : allNodeNames) {
                List<Double> successRates = new ArrayList<>();
                for (String week : weeks) {
                    Map<String, int[]> nodeData = weeklyNodeStats.get(week);
                    int[] stats = nodeData != null ? nodeData.get(nodeName) : null;

                    // 如果没有该 nodeName 的数据，补零
                    double percentage = 0.0;
                    if (stats != null) {
                        int totalCount = stats[0];
                        int zeroStatusCount = stats[1];
                        percentage = totalCount > 0
                                ? new BigDecimal(zeroStatusCount * 100.0 / totalCount)  // 计算百分比
                                .setScale(2, RoundingMode.HALF_UP)  // 设置保留两位小数并四舍五入
                                .doubleValue()  // 转为 double
                                : 0.0;  // 若 totalCount 为 0，则直接设为 0.0
                    }

                    successRates.add(percentage);
                }

                // 替换成功率为 0 的值
                replaceZeroWithAverage(successRates);

                nodeSuccessRates.put(nodeName, successRates);
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }

        // 构造返回数据
        timePeriods.put("week", weeks);
        Map<String, Object> response = new HashMap<>();
        response.put("timePeriods", timePeriods);
        response.put("nodeSuccessRates", nodeSuccessRates);

        return response;
    }


    public Map<String, Object> getNodeSuccessRateByQuarters() {
        // 返回数据结构
        Map<String, List<String>> timePeriods = new HashMap<>();
        List<String> quarters = new ArrayList<>();
        Map<String, List<Double>> nodeSuccessRates = new HashMap<>();

        // SQL 查询所有记录
        String sql = "SELECT `buildTime`, `nodeName`, COALESCE(`integratedStatus`, 0) AS `integratedStatus` FROM `cicd_integrated_info`;";

        // 使用 TreeMap 按时间和 nodeName 存储数据
        Map<String, Map<String, int[]>> quarterlyNodeStats = new TreeMap<>();

        try (Connection conn = druidDataSource.getConnection();
             PreparedStatement stmt = conn.prepareStatement(sql);
             ResultSet rs = stmt.executeQuery()) {

            while (rs.next()) {
                LocalDateTime buildTime = rs.getObject("buildTime", LocalDateTime.class);
                String nodeName = rs.getString("nodeName");
                int integratedStatus = rs.getInt("integratedStatus");

                // 获取自然季度，例如 "2024-Q1"
                String quarter = getQuarterPeriod(buildTime);

                // 初始化每季度每个 nodeName 的统计数据
                quarterlyNodeStats.putIfAbsent(quarter, new HashMap<>());
                quarterlyNodeStats.get(quarter).putIfAbsent(nodeName, new int[]{0, 0}); // totalCount, zeroStatusCount

                // 更新统计
                int[] stats = quarterlyNodeStats.get(quarter).get(nodeName);
                stats[0]++; // 总记录数加1
                if (integratedStatus == 0) {
                    stats[1]++; // integratedStatus == 0 的次数加1
                }
            }

            // 获取所有季度的顺序（已按升序排列）
            for (Map.Entry<String, Map<String, int[]>> quarterEntry : quarterlyNodeStats.entrySet()) {
                String quarter = quarterEntry.getKey();
                quarters.add(quarter);  // 添加季度
            }

            // 遍历每个 nodeName，初始化其在每季度的成功率列表
            Set<String> allNodeNames = new HashSet<>();
            for (Map.Entry<String, Map<String, int[]>> quarterEntry : quarterlyNodeStats.entrySet()) {
                Map<String, int[]> nodeData = quarterEntry.getValue();
                for (String nodeName : nodeData.keySet()) {
                    allNodeNames.add(nodeName);
                }
            }

            // 对每个 nodeName 遍历季度，计算每季度的成功率
            for (String nodeName : allNodeNames) {
                List<Double> successRates = new ArrayList<>();
                for (String quarter : quarters) {
                    Map<String, int[]> nodeData = quarterlyNodeStats.get(quarter);
                    int[] stats = nodeData != null ? nodeData.get(nodeName) : null;

                    // 如果没有该 nodeName 的数据，补零
                    double percentage = 0.0;
                    if (stats != null) {
                        int totalCount = stats[0];
                        int zeroStatusCount = stats[1];
                        percentage = totalCount > 0
                                ? new BigDecimal(zeroStatusCount * 100.0 / totalCount)
                                .setScale(2, RoundingMode.HALF_UP)
                                .doubleValue()
                                : 0.0;
                    }

                    successRates.add(percentage);
                }

                // 替换成功率为 0 的值
                replaceZeroWithAverage(successRates);

                nodeSuccessRates.put(nodeName, successRates);
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }

        // 构造返回数据
        timePeriods.put("quarter", quarters);
        Map<String, Object> response = new HashMap<>();
        response.put("timePeriods", timePeriods);
        response.put("nodeSuccessRates", nodeSuccessRates);

        return response;
    }


    public Map<String, Object> getNodeSuccessRateByYears() {
        // 返回数据结构
        Map<String, List<String>> timePeriods = new HashMap<>();
        List<String> years = new ArrayList<>();
        Map<String, List<Double>> nodeSuccessRates = new HashMap<>();

        // SQL 查询所有记录
        String sql = "SELECT `buildTime`, `nodeName`, COALESCE(`integratedStatus`, 0) AS `integratedStatus` FROM `cicd_integrated_info`;";

        // 使用 TreeMap 按时间和 nodeName 存储数据
        Map<String, Map<String, int[]>> yearlyNodeStats = new TreeMap<>();

        try (Connection conn = druidDataSource.getConnection();
             PreparedStatement stmt = conn.prepareStatement(sql);
             ResultSet rs = stmt.executeQuery()) {

            while (rs.next()) {
                LocalDateTime buildTime = rs.getObject("buildTime", LocalDateTime.class);
                String nodeName = rs.getString("nodeName");
                int integratedStatus = rs.getInt("integratedStatus");

                if (!nodeName.equals("CICD_C2_SOC")) // 仅保留指定节点
                    continue;

                // 获取自然年，例如 "2024"
                String year = String.valueOf(buildTime.getYear());

                // 初始化每年每个 nodeName 的统计数据
                yearlyNodeStats.putIfAbsent(year, new HashMap<>());
                yearlyNodeStats.get(year).putIfAbsent(nodeName, new int[]{0, 0}); // totalCount, zeroStatusCount

                // 更新统计
                int[] stats = yearlyNodeStats.get(year).get(nodeName);
                stats[0]++; // 总记录数加1
                if (integratedStatus == 0) {
                    stats[1]++; // integratedStatus == 0 的次数加1
                }
            }

            // 获取所有年的顺序（已按升序排列）
            for (Map.Entry<String, Map<String, int[]>> yearEntry : yearlyNodeStats.entrySet()) {
                String year = yearEntry.getKey();
                years.add(year);  // 添加年
            }

            // 遍历每个 nodeName，初始化其在每年的成功率列表
            Set<String> allNodeNames = new HashSet<>();
            for (Map.Entry<String, Map<String, int[]>> yearEntry : yearlyNodeStats.entrySet()) {
                Map<String, int[]> nodeData = yearEntry.getValue();
                for (String nodeName : nodeData.keySet()) {
                    allNodeNames.add(nodeName);
                }
            }

            // 对每个 nodeName 遍历年，计算每年的成功率
            for (String nodeName : allNodeNames) {
                List<Double> successRates = new ArrayList<>();
                for (String year : years) {
                    Map<String, int[]> nodeData = yearlyNodeStats.get(year);
                    int[] stats = nodeData != null ? nodeData.get(nodeName) : null;

                    // 如果没有该 nodeName 的数据，补零
                    double percentage = 0.0;
                    if (stats != null) {
                        int totalCount = stats[0];
                        int zeroStatusCount = stats[1];
                        percentage = totalCount > 0
                                ? new BigDecimal(zeroStatusCount * 100.0 / totalCount)  // 计算百分比
                                .setScale(2, RoundingMode.HALF_UP)  // 设置保留两位小数并四舍五入
                                .doubleValue()  // 转为 double
                                : 0.0;  // 若 totalCount 为 0，则直接设为 0.0
                    }

                    successRates.add(percentage);
                }

                // 替换成功率为 0 的值
                replaceZeroWithAverage(successRates);

                nodeSuccessRates.put(nodeName, successRates);
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }

        // 构造返回数据
        timePeriods.put("year", years);
        Map<String, Object> response = new HashMap<>();
        response.put("timePeriods", timePeriods);
        response.put("nodeSuccessRates", nodeSuccessRates);

        return response;
    }


    /**
     * 替换成功率为 0 的值为前后非零值的平均值
     */
    private void replaceZeroWithAverage(List<Double> successRates) {
        for (int i = 0; i < successRates.size(); i++) {
            if (successRates.get(i) == 0.0) {
                Double previous = null;
                Double next = null;

                // 寻找前一个非零值
                for (int j = i - 1; j >= 0; j--) {
                    if (successRates.get(j) != 0.0) {
                        previous = successRates.get(j);
                        break;
                    }
                }

                // 寻找后一个非零值
                for (int j = i + 1; j < successRates.size(); j++) {
                    if (successRates.get(j) != 0.0) {
                        next = successRates.get(j);
                        break;
                    }
                }

                // 计算平均值并替换零值
                if (previous != null || next != null) {
                    double average = (previous == null ? 0 : previous) + (next == null ? 0 : next);
                    int count = (previous == null ? 0 : 1) + (next == null ? 0 : 1);
                    double newValue = average / count;

                    // 保留两位小数
                    successRates.set(i, new BigDecimal(newValue)
                            .setScale(2, RoundingMode.HALF_UP)
                            .doubleValue());
                }
            }
        }
    }


    /**
     * 根据日期获取自然周周期，例如 "2024-W01"
     */
    private String getWeekPeriod(LocalDateTime releaseTime) {
        // 将 LocalDateTime 转换为 LocalDate，只保留日期部分
        LocalDate date = releaseTime.toLocalDate();

        // 获取年份和该日期的自然周
        int year = date.getYear();
        int week = releaseTime.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR);

        // 获取该周的开始日期（周一）
        LocalDate startOfWeek = date.with(IsoFields.WEEK_OF_WEEK_BASED_YEAR, week)
                .with(IsoFields.WEEK_BASED_YEAR, year)
                .with(java.time.temporal.TemporalAdjusters.previousOrSame(java.time.DayOfWeek.MONDAY));

        // 获取该周的结束日期（周日）
        LocalDate endOfWeek = startOfWeek.plusDays(6);

        // 使用 "MM/dd" 格式化日期
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd");
        return startOfWeek.format(formatter) + "-" + endOfWeek.format(formatter);
    }


    public Map<String, Object> getNodeSuccessRateByMonth() {
        // 返回数据结构
        Map<String, List<String>> timePeriods = new HashMap<>();
        List<String> months = new ArrayList<>();
        Map<String, List<Double>> nodeSuccessRates = new HashMap<>();

        // SQL 查询所有记录
        String sql = "SELECT `buildTime`, `nodeName`, COALESCE(`integratedStatus`, 0) AS `integratedStatus` FROM `cicd_integrated_info`;";

        // 使用 TreeMap 按时间和 nodeName 存储数据
        Map<String, Map<String, int[]>> monthlyNodeStats = new TreeMap<>();

        try (Connection conn = druidDataSource.getConnection();
             PreparedStatement stmt = conn.prepareStatement(sql);
             ResultSet rs = stmt.executeQuery()) {

            while (rs.next()) {
                LocalDateTime buildTime = rs.getObject("buildTime", LocalDateTime.class);
                String nodeName = rs.getString("nodeName");
                int integratedStatus = rs.getInt("integratedStatus");

                // 获取自然月周期，例如 "2024-01"
                String month = getMonthPeriod(buildTime);

                // 初始化每月每个 nodeName 的统计数据
                monthlyNodeStats.putIfAbsent(month, new HashMap<>());
                monthlyNodeStats.get(month).putIfAbsent(nodeName, new int[]{0, 0}); // totalCount, zeroStatusCount

                // 更新统计
                int[] stats = monthlyNodeStats.get(month).get(nodeName);
                stats[0]++; // 总记录数加1
                if (integratedStatus == 0) {
                    stats[1]++; // integratedStatus == 0 的次数加1
                }
            }

            // 获取所有月份的顺序（已按升序排列）
            for (Map.Entry<String, Map<String, int[]>> monthEntry : monthlyNodeStats.entrySet()) {
                String month = monthEntry.getKey();
                months.add(month);  // 添加月份
            }

            // 遍历每个 nodeName，初始化其在每个月的成功率列表
            Set<String> allNodeNames = new HashSet<>();
            for (Map.Entry<String, Map<String, int[]>> monthEntry : monthlyNodeStats.entrySet()) {
                Map<String, int[]> nodeData = monthEntry.getValue();
                for (String nodeName : nodeData.keySet()) {
                    allNodeNames.add(nodeName);
                }
            }

            // 对每个 nodeName 遍历月份，计算每个月的成功率
            for (String nodeName : allNodeNames) {
                List<Double> successRates = new ArrayList<>();
                for (String month : months) {
                    Map<String, int[]> nodeData = monthlyNodeStats.get(month);
                    int[] stats = nodeData != null ? nodeData.get(nodeName) : null;

                    // 如果没有该 nodeName 的数据，补零
                    double percentage = 0.0;
                    if (stats != null) {
                        int totalCount = stats[0];
                        int zeroStatusCount = stats[1];
                        percentage = totalCount > 0
                                ? new BigDecimal(zeroStatusCount * 100.0 / totalCount)
                                .setScale(2, RoundingMode.HALF_UP)
                                .doubleValue()
                                : 0.0;
                    }

                    successRates.add(percentage);
                }

                // 替换成功率为 0 的值
                replaceZeroWithAverage(successRates);

                nodeSuccessRates.put(nodeName, successRates);
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }

        // 构造返回数据
        timePeriods.put("month", months);
        Map<String, Object> response = new HashMap<>();
        response.put("timePeriods", timePeriods);
        response.put("nodeSuccessRates", nodeSuccessRates);

        return response;
    }

    /**
     * 根据日期获取自然月周期，例如 "2024-01"
     */
    private String getMonthPeriod(LocalDateTime buildTime) {
        return buildTime.getYear() + "-" + String.format("%02d", buildTime.getMonthValue());
    }

    /**
     * 根据日期获取自然季度，例如 "2024-Q1"
     */
    private String getQuarterPeriod(LocalDateTime buildTime) {
        int year = buildTime.getYear();
        int month = buildTime.getMonthValue();
        int quarter = (month - 1) / 3 + 1; // 计算季度
        return year + "-第" + quarter + "季度";
    }
}
